package org.example.camundaapp.bpm.service;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.model.bpmn.Bpmn;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.instance.*;
import org.camunda.bpm.model.bpmn.instance.Process;
import org.camunda.bpm.model.bpmn.instance.bpmndi.*;
import org.camunda.bpm.model.bpmn.instance.dc.Bounds;
import org.camunda.bpm.model.bpmn.instance.di.Waypoint;
import org.example.camundaapp.utils.BpmnToImageConverter;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

/**
 * @className: JsonToBpmnConverter2
 * @author: ZHRJ
 * @date: 2025-06-25 13:39
 * @Version: 1.0
 * @description:
 */
@Slf4j
@Component
public class JsonToBpmnConverter3 {
    //@Value("${camunda.modeler.exporter-version}")
    private String exporterVersion = "7.19.0";

    @PostConstruct
    public void init() {
        log.info("注入的 exporterVersion: {}", exporterVersion); // 若输出 5.19.0 则成功
    }
    /**
     * JSON转BPMN模型并输出XML字符串
     * @param bpmnJson
     * @return
     */
    public String jsonToBPMNConvert(JSONObject bpmnJson) throws Exception {

        // 存储节点ID到FlowNode的映射（用于后续连接线查找）
        Map<String, FlowNode> nodeMap = new HashMap<>();

        BpmnModelInstance modelInstance = Bpmn.createEmptyModel();
        Definitions definitions = modelInstance.newInstance(Definitions.class); // 创建定义, 相当于一个容器
        definitions.setTargetNamespace("https://camunda.org/examples");
        definitions.setExporter("Camunda Modeler");
        //definitions.setExporterVersion(exporterVersion);
        // 显式设置exporter和exporterVersion的命名空间（BPMN标准命名空间）
        definitions.setAttributeValueNs(
                "http://www.omg.org/spec/BPMN/20100524/MODEL", // BPMN标准命名空间
                "exporter",
                "Camunda Modeler"
        );
        definitions.setAttributeValueNs(
                "http://www.omg.org/spec/BPMN/20100524/MODEL",
                "exporterVersion",
                exporterVersion
        );

        modelInstance.setDefinitions(definitions);

        // ==================模块分割=====================

        JSONObject processJson = bpmnJson.getJSONObject("process");
        // 1. 创建流程（Process），Process相当于图纸，后续工作就是在图纸上添加节点和连线
        Process process = modelInstance.newInstance(Process.class);
        process.setId(processJson.getString("id"));
        process.setName(processJson.getString("name"));

        //Object isExecutable = processJson.get("isExecutable");
        //if(null != isExecutable){
        //    process.setExecutable((boolean)isExecutable); // 显式声明为可执行流程，作用是：创建流程时，流程图会自动生成节点和连线，否则需要手动添加节点和连线
        //}

        // 设置Camunda扩展属性（从根JSON获取diagram.id）
        if (bpmnJson.containsKey("diagram")) { // 为了部署过程可以生成图形资源（svg\png）
            String diagramId = bpmnJson.getJSONObject("diagram").getString("id");
            process.setAttributeValueNs("http://camunda.org/schema/1.0/bpmn",
                    "diagram", diagramId);
        }

        // 设置流程属性
        if (processJson.containsKey("isExecutable")) {
            process.setExecutable(processJson.getBoolean("isExecutable"));
        }
        if (processJson.containsKey("historyTimeToLive")) {
            process.setAttributeValueNs("http://camunda.org/schema/1.0/bpmn",
                    "historyTimeToLive",
                    processJson.getString("historyTimeToLive"));
        }

        definitions.addChildElement(process);

        // ==================模块分割=====================

        // 2. 创建 DI 元素（关键新增），用于定义图形位置
        BpmnDiagram bpmnDiagram = modelInstance.newInstance(BpmnDiagram.class);
        JSONObject diagramJson = bpmnJson.getJSONObject("diagram");
        String diagramId = diagramJson.getString("id");
        bpmnDiagram.setId(diagramId);
        definitions.addChildElement(bpmnDiagram); // 将 DI 图添加到 Definitions

        JSONObject diagramPlane = diagramJson.getJSONObject("plane");
        String diagramPlaneId = diagramPlane.getString("id");
        String diagramBpmnElement =diagramPlane.getString("bpmnElement");
        BpmnPlane bpmnPlane = modelInstance.newInstance(BpmnPlane.class);
        bpmnPlane.setId(diagramPlaneId);
        bpmnPlane.setBpmnElement(process); // 关联到流程

        // 强制设置isExpanded属性
        if (bpmnPlane.getBpmnElement() instanceof Process) {
            bpmnPlane.setAttributeValueNs("http://camunda.org/schema/1.0/bpmn",
                    "isExpanded", "true"); // 作用在流程图上，控制流程图是否展开
        }

        bpmnDiagram.addChildElement(bpmnPlane);

        // ==================模块分割=====================

        JSONArray nodes = processJson.getJSONArray("nodes");
        for (int i = 0; i < nodes.size(); i++) {
            JSONObject node = nodes.getJSONObject(i);
            String type = node.getString("type");
            String nodeId = node.getString("id");
            String nodeName = node.getString("name");


            switch (type) {
                case "startEvent":
                case "endEvent":
                case "task":
                case "userTask":
                case "serviceTask":
                case "exclusiveGateway":
                case "intermediateThrowEvent": // 中间抛出事件

                    handleFlowNode(node, modelInstance, process, bpmnPlane, nodeMap);
                    break;
                case "sequenceFlow": // 连接线节点
                    handleSequenceFlow(node, modelInstance, process, bpmnPlane, nodeMap);
                    break;
                default:
                    log.error(">不支持节点类型:{} ",type);
                    throw new IllegalArgumentException("不支持节点类型Unsupported node type: " + type);
            }

            // ==================模块分割=====================

        }


        //Bpmn.writeModelToFile(new File("target/new-process.bpmn"), modelInstance);
        String bpmnXml = Bpmn.convertToString(modelInstance);

        // 生成SVG图形（关键新增）
        //String svgContent = BpmnDiagramConverter.getInstance().convertToString(modelInstance);
        //byte[] svgBytes = svgContent.getBytes(StandardCharsets.UTF_8);
        // 可选：将SVG保存到文件（根据需求）
        // Files.write(Paths.get("target/process-diagram.svg"), svgBytes);

        return bpmnXml;
    }

    /**
     * json转为bpmn，bpmn生成png
     * @param bpmnJson
     * @return bpmnXml,pngBytes
     * @throws Exception
     */
    public Map<String,Object> jsonToBPMNConvertAndPng(JSONObject bpmnJson) throws Exception {

        // 存储节点ID到FlowNode的映射（用于后续连接线查找）
        Map<String, FlowNode> nodeMap = new HashMap<>();

        BpmnModelInstance modelInstance = Bpmn.createEmptyModel();
        Definitions definitions = modelInstance.newInstance(Definitions.class); // 创建定义, 相当于一个容器
        definitions.setTargetNamespace("https://camunda.org/examples");
        definitions.setExporter("Camunda Modeler");
        //definitions.setExporterVersion(exporterVersion);
        // 显式设置exporter和exporterVersion的命名空间（BPMN标准命名空间）
        definitions.setAttributeValueNs(
                "http://www.omg.org/spec/BPMN/20100524/MODEL", // BPMN标准命名空间
                "exporter",
                "Camunda Modeler"
        );
        definitions.setAttributeValueNs(
                "http://www.omg.org/spec/BPMN/20100524/MODEL",
                "exporterVersion",
                exporterVersion
        );

        modelInstance.setDefinitions(definitions);

        // ==================模块分割=====================

        JSONObject processJson = bpmnJson.getJSONObject("process");
        // 1. 创建流程（Process），Process相当于图纸，后续工作就是在图纸上添加节点和连线
        Process process = modelInstance.newInstance(Process.class);
        process.setId(processJson.getString("id"));
        process.setName(processJson.getString("name"));

        //Object isExecutable = processJson.get("isExecutable");
        //if(null != isExecutable){
        //    process.setExecutable((boolean)isExecutable); // 显式声明为可执行流程，作用是：创建流程时，流程图会自动生成节点和连线，否则需要手动添加节点和连线
        //}

        // 设置Camunda扩展属性（从根JSON获取diagram.id）
        if (bpmnJson.containsKey("diagram")) { // 为了部署过程可以生成图形资源（svg\png）
            String diagramId = bpmnJson.getJSONObject("diagram").getString("id");
            process.setAttributeValueNs("http://camunda.org/schema/1.0/bpmn",
                    "diagram", diagramId);
        }

        // 设置流程属性
        if (processJson.containsKey("isExecutable")) {
            process.setExecutable(processJson.getBoolean("isExecutable"));
        }
        if (processJson.containsKey("historyTimeToLive")) {
            process.setAttributeValueNs("http://camunda.org/schema/1.0/bpmn",
                    "historyTimeToLive",
                    processJson.getString("historyTimeToLive"));
        }

        definitions.addChildElement(process);

        // ==================模块分割=====================

        // 2. 创建 DI 元素（关键新增），用于定义图形位置
        BpmnDiagram bpmnDiagram = modelInstance.newInstance(BpmnDiagram.class);
        JSONObject diagramJson = bpmnJson.getJSONObject("diagram");
        String diagramId = diagramJson.getString("id");
        bpmnDiagram.setId(diagramId);
        definitions.addChildElement(bpmnDiagram); // 将 DI 图添加到 Definitions

        JSONObject diagramPlane = diagramJson.getJSONObject("plane");
        String diagramPlaneId = diagramPlane.getString("id");
        String diagramBpmnElement =diagramPlane.getString("bpmnElement");
        BpmnPlane bpmnPlane = modelInstance.newInstance(BpmnPlane.class);
        bpmnPlane.setId(diagramPlaneId);
        bpmnPlane.setBpmnElement(process); // 关联到流程

        // 强制设置isExpanded属性
        if (bpmnPlane.getBpmnElement() instanceof Process) {
            bpmnPlane.setAttributeValueNs("http://camunda.org/schema/1.0/bpmn",
                    "isExpanded", "true"); // 作用在流程图上，控制流程图是否展开
        }

        bpmnDiagram.addChildElement(bpmnPlane);

        // ==================模块分割=====================

        JSONArray nodes = processJson.getJSONArray("nodes");
        for (int i = 0; i < nodes.size(); i++) {
            JSONObject node = nodes.getJSONObject(i);
            String type = node.getString("type");
            String nodeId = node.getString("id");
            String nodeName = node.getString("name");


            switch (type) {
                case "startEvent":
                case "endEvent":
                case "task":
                case "userTask":
                case "serviceTask":
                case "exclusiveGateway":
                case "parallelGateway":
                case "intermediateThrowEvent": // 中间抛出事件

                    handleFlowNode(node, modelInstance, process, bpmnPlane, nodeMap);
                    break;
                case "sequenceFlow": // 连接线节点
                    handleSequenceFlow(node, modelInstance, process, bpmnPlane, nodeMap);
                    break;
                default:
                    log.error(">不支持节点类型:{} ",type);
                    throw new IllegalArgumentException("不支持节点类型Unsupported node type: " + type);
            }

            // ==================模块分割=====================

        }


        //Bpmn.writeModelToFile(new File("target/new-process.bpmn"), modelInstance);
        String bpmnXml = Bpmn.convertToString(modelInstance);

        // 生成PNG图形
        byte[] pngBytes = BpmnToImageConverter.convertBpmnXmlToPngBytes(bpmnXml);

        Map<String,Object> result = new HashMap<>();
        result.put("bpmnXml",bpmnXml);
        result.put("pngBytes",pngBytes);
        return result;
    }


    /**
     * 处理流程节点
     */
    private void handleFlowNode(JSONObject node, BpmnModelInstance modelInstance,
                                Process process, BpmnPlane bpmnPlane,
                                Map<String, FlowNode> nodeMap) {
        String nodeId = node.getString("id");
        String type = node.getString("type");
        String name = node.getString("name");
        JSONObject di = node.getJSONObject("di");

        // 创建节点实例
        FlowNode flowNode = createFlowNode(modelInstance, process, bpmnPlane,
                nodeId, name, type, di);

        // 设置节点特定属性
        if (flowNode instanceof UserTask) { // 用户任务节点，设置办理人或候选人
            String assignee = node.getString("assignee");
            if (assignee != null) {
                ((UserTask) flowNode).setCamundaAssignee(assignee);
            }

            // 处理候选人模式（任务不直接分配给具体用户，而是分配给一组候选人）
            String candidateUsers = node.getString("candidateUsers");
            if (candidateUsers != null) {
                ((UserTask) flowNode).setCamundaCandidateUsers(candidateUsers);
            }
        }

        // 处理排他网关默认序列流
        if (flowNode instanceof ExclusiveGateway) {
            ExclusiveGateway exclusiveGateway = (ExclusiveGateway) flowNode;
            String defaultFlowId = node.getString("default");
            if (defaultFlowId != null) {
                nodeMap.put(nodeId + "_defaultFlow", exclusiveGateway);
            }
        }

        // 处理多实例任务
        if (flowNode instanceof Task) {
            JSONObject multiInstanceLoop = node.getJSONObject("multiInstanceLoop");
            if (multiInstanceLoop != null) {
                handleMultiInstanceLoop(modelInstance, (Task) flowNode, multiInstanceLoop);
            }
        }

        // 处理 incoming 和 outgoing 序列流，应该放到创建完序列流后再创建
        /*JSONArray incomingArray = node.getJSONArray("incoming");
        if (incomingArray != null) {
            for (int i = 0; i < incomingArray.size(); i++) {
                String incomingFlowId = incomingArray.getString(i);
                // 查找对应的 SequenceFlow
                SequenceFlow incomingFlow = process.getChildElementsByType(SequenceFlow.class).stream()
                        .filter(flow -> flow.getId().equals(incomingFlowId))
                        .findFirst()
                        .orElse(null);
                if (incomingFlow != null) {
                    flowNode.getIncoming().add(incomingFlow);
                }
            }
        }

        JSONArray outgoingArray = node.getJSONArray("outgoing");
        if (outgoingArray != null) {
            for (int i = 0; i < outgoingArray.size(); i++) {
                String outgoingFlowId = outgoingArray.getString(i);
                // 查找对应的 SequenceFlow
                SequenceFlow outgoingFlow = process.getChildElementsByType(SequenceFlow.class).stream()
                        .filter(flow -> flow.getId().equals(outgoingFlowId))
                        .findFirst()
                        .orElse(null);
                if (outgoingFlow != null) {
                    flowNode.getOutgoing().add(outgoingFlow);
                }
            }
        }*/

        // 存储节点引用
        nodeMap.put(nodeId, flowNode);
    }

    /**
     * 处理多实例任务
     * @param modelInstance bpmn模型实例
     * @param task 任务节点
     * @param multiInstanceLoop 多实例任务配置(json)
     */
    private void handleMultiInstanceLoop(BpmnModelInstance modelInstance, Task task, JSONObject multiInstanceLoop) {
        MultiInstanceLoopCharacteristics loopCharacteristics = modelInstance.newInstance(MultiInstanceLoopCharacteristics.class);

        // 设置集合和元素变量
        String collection = multiInstanceLoop.getString("collection");
        String elementVariable = multiInstanceLoop.getString("elementVariable");
        if (collection != null) {
            loopCharacteristics.setCamundaCollection(collection);
        }
        if (elementVariable != null) {
            loopCharacteristics.setCamundaElementVariable(elementVariable);
        }

        // 循环基数
        String loopCardinality = multiInstanceLoop.getString("loopCardinality");
        if (loopCardinality != null) {
            LoopCardinality cardinality = modelInstance.newInstance(LoopCardinality.class);
            cardinality.setTextContent(loopCardinality); // 这里直接设置文本内容
            loopCharacteristics.setLoopCardinality(cardinality);
        }

        // 完成条件
        String completionCondition = multiInstanceLoop.getString("completionCondition");
        if (completionCondition != null) {
            CompletionCondition condition = modelInstance.newInstance(CompletionCondition.class);
            condition.setTextContent(completionCondition); // 直接设置文本内容
            loopCharacteristics.setCompletionCondition(condition);
        }

        // 处理isSequential属性，没有默认是false，表示并行执行，true表示顺序执行
        if(multiInstanceLoop.containsKey("isSequential")){
            boolean isSequential = multiInstanceLoop.getBoolean("isSequential");
            loopCharacteristics.setSequential(isSequential);
        }

        // 并非标准 BPMN 规范内容，可添加扩展属性，用于存储多实例任务类型。例如type
        // "multiInstanceLoop": {
        //          "collection": "${userTwoList}",
        //          "elementVariable": "assignee",
        //          "completionCondition": "${nrOfCompletedInstances/nrOfInstances > 0.3 }",
        //          "type": "比例签"
        //        },
        if (multiInstanceLoop.containsKey("type")) {
            String type = multiInstanceLoop.getString("type"); // --> camunda:multiInstanceType="比例签"
            // 使用 Camunda 扩展属性存储 type 信息
            loopCharacteristics.setAttributeValueNs("http://camunda.org/schema/1.0/bpmn", "multiInstanceType", type);
        }

        task.setLoopCharacteristics(loopCharacteristics);
    }

    /**
     * 创建流程节点并设置图形位置
     */
    private FlowNode createFlowNode(BpmnModelInstance modelInstance, Process process,
                                    BpmnPlane bpmnPlane, String nodeId, String name,
                                    String type, JSONObject di) {
        Class<? extends FlowNode> nodeClass = getNodeClass(type);
        // 1、创建流程节点（StartEvent、UserTask、EndEvent）
        FlowNode node = modelInstance.newInstance(nodeClass);
        node.setId(nodeId);
        node.setName(name);
        // 2、绘制到图纸上
        process.addChildElement(node);

        // 设置图形位置
        JSONObject boundsJson = di.getJSONObject("bounds");
        BpmnShape shape = modelInstance.newInstance(BpmnShape.class);
        shape.setId(di.getString("id"));
        shape.setBpmnElement(node);

        Bounds bounds = modelInstance.newInstance(Bounds.class);
        bounds.setX(boundsJson.getInteger("x"));
        bounds.setY(boundsJson.getInteger("y"));
        bounds.setWidth(boundsJson.getInteger("width"));
        bounds.setHeight(boundsJson.getInteger("height"));
        shape.setBounds(bounds);
        bpmnPlane.addChildElement(shape);

        // 网关标记可见性
        /*if (node instanceof ExclusiveGateway && di.containsKey("isMarkerVisible")) {
            ((ExclusiveGateway) node).setMarkerVisible(di.getBoolean("isMarkerVisible")); Api不支持，暂不处理
        }*/

        return node;
    }

    /**
     * 处理连接线
     */
    private void handleSequenceFlow(JSONObject flow, BpmnModelInstance modelInstance,
                                    Process process, BpmnPlane bpmnPlane,
                                    Map<String, FlowNode> nodeMap) {
        String flowId = flow.getString("id");
        String sourceRef = flow.getString("sourceRef");
        String targetRef = flow.getString("targetRef");

        // 获取源和目标节点
        FlowNode source = nodeMap.get(sourceRef);
        FlowNode target = nodeMap.get(targetRef);

        if (source == null || target == null) {
            log.error("连接线 {} 引用了不存在的节点: source={}, target={}", flowId, sourceRef, targetRef);
            throw new IllegalArgumentException("节点引用不存在");
        }

        // 创建序列流
        SequenceFlow sequenceFlow = modelInstance.newInstance(SequenceFlow.class);
        sequenceFlow.setId(flowId);
        sequenceFlow.setName(flow.getString("name"));
        sequenceFlow.setSource(source);
        sequenceFlow.setTarget(target);
        process.addChildElement(sequenceFlow);

        // 更新 source/outgoing 和 target/incoming，对应的是任务节点里的"incoming": ["Flow_01wvf4l"],"outgoing": ["Flow_0rzeycn"],
        source.getOutgoing().add(sequenceFlow);
        target.getIncoming().add(sequenceFlow);

        // 设置条件表达式
        if (flow.containsKey("conditionExpression")) {
            //FormalExpression condition = modelInstance.newInstance(FormalExpression.class);
            //condition.setTextContent(flow.getString("conditionExpression"));
            ConditionExpression conditionExpression = modelInstance.newInstance(ConditionExpression.class);
            conditionExpression.setTextContent(flow.getString("conditionExpression"));
            sequenceFlow.setConditionExpression(conditionExpression);
        }

        // 处理默认序列流
        if (flow.containsKey("isDefault") && source instanceof ExclusiveGateway) {
            ExclusiveGateway exclusiveGateway = (ExclusiveGateway) source;
            exclusiveGateway.setDefault(sequenceFlow);
        }

        // 创建图形连线
        JSONObject di = flow.getJSONObject("di");
        BpmnEdge edge = modelInstance.newInstance(BpmnEdge.class);
        edge.setId(di.getString("id"));
        edge.setBpmnElement(sequenceFlow);

        // 添加路径点
        JSONArray waypoints = di.getJSONArray("waypoints");
        for (int i = 0; i < waypoints.size(); i++) {
            JSONObject wp = waypoints.getJSONObject(i);
            Waypoint waypoint = modelInstance.newInstance(Waypoint.class);
            waypoint.setX(wp.getInteger("x"));
            waypoint.setY(wp.getInteger("y"));
            edge.addChildElement(waypoint);
        }

        // 添加标签位置
        if (di.containsKey("label")) {
            JSONObject labelJson = di.getJSONObject("label").getJSONObject("bounds");
            BpmnLabel bpmnLabel = modelInstance.newInstance(BpmnLabel.class);

            Bounds labelBounds = modelInstance.newInstance(Bounds.class);
            labelBounds.setX(labelJson.getInteger("x"));
            labelBounds.setY(labelJson.getInteger("y"));
            labelBounds.setWidth(labelJson.getInteger("width"));
            labelBounds.setHeight(labelJson.getInteger("height"));

            bpmnLabel.setBounds(labelBounds);
            edge.setBpmnLabel(bpmnLabel);
        }

        bpmnPlane.addChildElement(edge); // 将连接线图形添加到平面
    }

    /**
     * 根据节点类型获取对应的Class
     * @param type
     * @return
     */
    private Class<? extends FlowNode> getNodeClass(String type) {
        switch (type) {
            case "startEvent": return StartEvent.class;
            case "endEvent": return EndEvent.class;
            case "task": return Task.class;
            case "userTask": return UserTask.class;
            case "serviceTask": return ServiceTask.class;
            case "exclusiveGateway": return ExclusiveGateway.class; // 排他网关
            case "intermediateThrowEvent": return IntermediateThrowEvent.class;
            case "parallelGateway": return ParallelGateway.class; // 并行网关类型
            default:
                log.error(">未知节点类型:{} " ,type);
                throw new IllegalArgumentException("未知节点类型: " + type);
        }
    }

    /**
     * 创建流程节点并设置图形位置
     * @param modelInstance
     * @param process
     * @param bpmnPlane
     * @param nodeId
     * @param nodeClass
     * @param x
     * @param y
     * @param width
     * @param height
     * @return
     * @param <T>
     */
    private <T extends FlowNode> T createFlowNode(
            BpmnModelInstance modelInstance,
            Process process,
            BpmnPlane bpmnPlane,
            String nodeId,
            String nodeName,
            Class<T> nodeClass,
            String diId,
            int x, int y, int width, int height) {

        // 1、创建流程节点（StartEvent、UserTask、EndEvent）
        T node = modelInstance.newInstance(nodeClass);
        node.setId(nodeId);
        node.setName(nodeName);
        // 2、绘制到图纸上
        process.addChildElement(node);

        // 设置图形位置（BpmnShape）
        BpmnShape shape = modelInstance.newInstance(BpmnShape.class);
        shape.setId(diId);
        shape.setBpmnElement(node);
        Bounds bounds = modelInstance.newInstance(Bounds.class);
        bounds.setX(x);
        bounds.setY(y);
        bounds.setWidth(width);
        bounds.setHeight(height);
        shape.setBounds(bounds);
        bpmnPlane.addChildElement(shape);

        return node;
    }

    /**
     * 创建连接线并设置路径
     * @param modelInstance
     * @param process
     * @param bpmnPlane
     * @param flowId
     * @param source 源节点
     * @param target 目标节点
     * @param startX
     * @param startY
     * @param endX
     * @param endY
     */
    private void connectSequenceFlow(
            BpmnModelInstance modelInstance,
            Process process,
            BpmnPlane bpmnPlane,
            String flowId,
            FlowNode source,
            FlowNode target,
            int startX, int startY, int endX, int endY) {

        // 创建SequenceFlow并关联到流程
        SequenceFlow flow = modelInstance.newInstance(SequenceFlow.class);
        flow.setId(flowId);
        flow.setSource(source);
        flow.setTarget(target);
        process.addChildElement(flow);

        // 创建连接线路（BpmnEdge）并设置路径点
        BpmnEdge edge = modelInstance.newInstance(BpmnEdge.class);
        edge.setBpmnElement(flow);
        // 起点（从源节点右侧中间出发）
        Waypoint startWaypoint = modelInstance.newInstance(Waypoint.class);
        startWaypoint.setX(startX);
        startWaypoint.setY(startY);
        // 终点（到目标节点左侧中间）
        Waypoint endWaypoint = modelInstance.newInstance(Waypoint.class);
        endWaypoint.setX(endX);
        endWaypoint.setY(endY);
        edge.addChildElement(startWaypoint);
        edge.addChildElement(endWaypoint);
        bpmnPlane.addChildElement(edge);
    }
}
